package ru.spb.osll.myfit.server;

import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import ru.spb.osll.myfit.server.fixtureiterator.FileFactory;

public class MyFitClassLoaderFactory {
  private Logger log = Logger.getLogger(getClass());
  private FileFactory m_fileFactory;

  public MyFitClassLoaderFactory(FileFactory fileFactory) {
    m_fileFactory = fileFactory;
  }

  public URLClassLoader createClassLoader(String... dirNames) {
    return createClassLoader(Collections.<URL> emptyList(), dirNames);
  }

  public URLClassLoader createClassLoader(List<URL> listURL, String... dirNames) {
    LinkedList<URL> urls = new LinkedList<URL>();
    urls.addAll(listURL);

    for (String dirName : dirNames) {
      File dir = m_fileFactory.createFile(dirName);
      String[] jars = dir.list(new FilenameFilter() {
        @Override
        public boolean accept(File dir, String name) {
          return name.endsWith(".jar") || name.endsWith(".zip");
        }
      });
      if (jars != null)
        addURLs(urls, dir, jars);
    }

    boolean isStandaloneRun = System.getProperty("catalina.base") == null;

    if (isStandaloneRun) {
      if(getClass().getClassLoader() instanceof URLClassLoader) {
        URLClassLoader classLoader = (URLClassLoader) getClass().getClassLoader();
        for(URL url : classLoader.getURLs()) {
          urls.add(url);
        }
      }
    }

    for (URL url : urls) {
      log.info("ClassPath: " + url);
    }

    return new URLClassLoader(urls.toArray(new URL[urls.size()]), getTopParentClassLoader());
  }

  private ClassLoader getTopParentClassLoader() {
    ClassLoader classLoader = getClass().getClassLoader();

    while (classLoader.getParent() != null) {
      classLoader = classLoader.getParent();
    }

    return classLoader;
  }

  private void addURLs(LinkedList<URL> urls, File dir, String[] jars) {
    for (String jar : jars) {
      try {
        urls.add(m_fileFactory.createFile(dir, jar).toURI().toURL());
      } catch (MalformedURLException e) {
        log.error("error creating URL", e);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
}
